var input = File.ReadAllLines(Path.Combine(Path.GetDirectoryName(Util.CurrentQueryPath), "..", "day22.txt")).ToList(); IEnumerable> Split(IEnumerator e, Func splitFunc) { while (e.MoveNext()) { var ret = new List(); while (!splitFunc(e.Current)) { ret.Add(e.Current); e.MoveNext();} yield return ret; } } int ScoreHand(List hand) => hand.Select((c,i)=> (c,i)).OrderByDescending(h => h.i).Select((h,i)=> h.c*(i+1)).Sum(); var hands = Split(input.GetEnumerator(), string.IsNullOrEmpty).Select(i => i.Skip(1).Select(int.Parse).ToList()).ToList(); while (hands.All(h => h.Any())) { var nextCards = hands.Select(h => h.First()).OrderByDescending(h => h).ToArray(); var winningHand = hands.Single(h => h[0] == nextCards[0]); hands.ForEach(h => h.RemoveAt(0)); winningHand.AddRange(nextCards); } var part1 = ScoreHand(hands.Single(h => h.Any())); part1.Dump(); hands = Split(input.GetEnumerator(), string.IsNullOrEmpty).Select(i => i.Skip(1).Select(int.Parse).ToList()).ToList(); int RecursiveCombat(List p1, List p2) { var infiniteGamePrevention = new HashSet(); while (p1.Any() && p2.Any()) { var key = string.Join(":", string.Join(",", p1), string.Join(",", p2)); if (infiniteGamePrevention.Contains(key)) break; infiniteGamePrevention.Add(key); var p1c = p1[0]; var p2c = p2[0]; p1.RemoveAt(0); p2.RemoveAt(0); var winner = p1c <= p1.Count && p2c <= p2.Count ? RecursiveCombat (p1.Select(p => p).Take(p1c).ToList(), p2.Select(p => p).Take(p2c).ToList()) : p1c > p2c ? 1 : 2; if (winner == 1) { p1.Add(p1c); p1.Add(p2c); } else { p2.Add(p2c); p2.Add(p1c); } } return p1.Any() ? 1 : 2; } var win = RecursiveCombat(hands[0], hands[1]); var part2 = ScoreHand(win == 1 ? hands[0] : hands[1]); part2.Dump();